package com.rwy.web.controller;

import java.util.HashMap;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.function.Predicate;

import com.rwy.dto.device.HandleFaultTaskDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSON;
import com.rwy.dto.device.EmployeeDTO;
import com.rwy.dto.device.HandleFaultDeviceItemDTO;
import com.rwy.dto.device.HandleFaultRecordDTO;
import com.rwy.service.HandleFaultDeviceService;
import com.rwy.util.CommonController;
import com.rwy.util.JsonObject;
import com.rwy.util.ObjectUtil;
import com.rwy.util.PageInfo;
import com.rwy.util.RWYException;
import com.rwy.util.ResponseJson;
import com.rwy.util.StringUtil;
import com.rwy.util.constant.FaultDeviceConstant;
import com.rwy.util.constant.FaultDeviceEnum;
import com.tool.http.httpclient.HttpClientUtil;
import com.tool.util.http.common.HttpConfig;

import lombok.extern.log4j.Log4j;

/* handle device */
@RestController
@RequestMapping("/device")
@Log4j
public class HandleFaultController extends CommonController {

	@Autowired
	HandleFaultDeviceService handleService;
	
	@RequestMapping(value = "handleFault/{type}", method=RequestMethod.GET, produces = "application/json; charset=UTF-8")
	public JsonObject handleDeviceItem(@PathVariable("type") Integer type, Integer pageSize, Integer page) throws Exception{
		JsonObject json = JsonObject.getInstance();
		boolean pass = true;
		if(typePred().negate().test(type)) {
			pass = false;
		}
		if (pass) {
			PageInfo<HandleFaultDeviceItemDTO> list = handleService.gethandleFaultItem(HandleFaultDeviceItemDTO.builder().handStatus(type).employeeId(getEmployee().getEmployeeID()).build().buildPage(page).buildPageSize(pageSize));
			json.setPage(list);
		}
		setJsonMesasge(json, pass);
		return json;
	}

	
	@RequestMapping(value = "handleFault", method=RequestMethod.POST, produces = "application/json; charset=UTF-8")
	public JsonObject saveHandleDevice(HandleFaultRecordDTO record) throws Exception {
		JsonObject json = JsonObject.getInstance();
		EmployeeDTO user = getEmployee();
		boolean pass = true;
		if (validateRecord().negate().test(record) || user == null) {
			pass = false;
			log.info("param error..");
		}
		record.setEmployID(user.getEmployeeID());
		record.setEmployName(user.getEmployeeName());

		HandleFaultTaskDTO task = handleService.getFaultDeviceTaskByHandIDAndEmployeeID(user.getEmployeeID(), record.getHandID());
		Assert.notNull(task);

		if (pass) {
			record.setTerminalID(task.getTerminalID());
			uploadImg(record);
			handleService.saveMaintainRecord(record);
		}
		setJsonMesasge(json, pass);
		return json;
	}
	
	private void uploadImg(HandleFaultRecordDTO record) throws Exception {
		ExecutorService executor = Executors.newCachedThreadPool();
		boolean pass = true;
		//FutureTask<ResponseJson> deviceTask = new FutureTask<ResponseJson>(new UploadThread(buildParam(record.getDevicePhoto())));
		//FutureTask<ResponseJson> printerTask = new FutureTask<ResponseJson>(new UploadThread(buildParam(record.getPrinterPhoto())));
		//FutureTask<ResponseJson> testTask = new FutureTask<ResponseJson>(new UploadThread(buildParam(record.getTestPhoto())));
		///executor.submit(deviceTask);
		//executor.submit(printerTask);
		//executor.submit(testTask);
		Future<ResponseJson> device = executor.submit(new UploadThread(buildParam(record.getDevicePhoto(), record.getTerminalID())));
		Future<ResponseJson> printer = executor.submit(new UploadThread(buildParam(record.getPrinterPhoto(), record.getTerminalID())));
		Future<ResponseJson> test = executor.submit(new UploadThread(buildParam(record.getTestPhoto(), record.getTerminalID())));

		Predicate<ResponseJson> predTask = s->{ return s!= null && !StringUtil.isEmpty(s.getSource_url());};

		if (pass && predTask.test(device.get())) {
			record.setDevicePhoto(device.get().getSource_url());
		} else {
			pass = false;
		}
		if (pass && predTask.test(printer.get())) {
			record.setTestPhoto(printer.get().getSource_url());
		} else {
			pass = false;
		}
		
		if (pass && predTask.test(test.get())) {
			record.setPrinterPhoto(test.get().getSource_url());
		} else {
			pass = false;
		}
		if (!pass) {
			throw  RWYException.create(400);
		}
		executor.shutdown();
	}
	

	private String buildParam(String media_id, int terminalID) throws Exception {
		StringBuffer sb = new StringBuffer();
		sb.append("{\"app_key\":\"rsmina\", ");
		sb.append("\"app_secret\": \"0cbf52a63dd3f7ef4f32a519166a442b\", ");
		sb.append("\"wechat_acount\":\"gh_43f2f461d7ac\", ");
		sb.append("\"method\": \"upload_file_by_media_id\", ");
		sb.append("\"access_token\":\""+ getFaultAccessToken().getAccess_token() +"\", ");
		sb.append("\"media_id\": \""+ media_id +"\", ");
		sb.append("\"terminal_id\":"+ terminalID );
		sb.append("}");
		return sb.toString();
	}
	
	@RequestMapping(value = "handleFault/{type}/{id}", method = RequestMethod.GET, produces = "application/json; charset=UTF-8")
	public JsonObject handleFaultDetail(@PathVariable("type")Integer type, @PathVariable("id") Integer id) throws Exception {
		JsonObject json = JsonObject.getInstance();
		json.setData(handleService.gethandleRecordDetail(type, getEmployee().getEmployeeID(), id));
		setJsonMesasge(json);
		return json;
	}
	
	@RequestMapping(value = "desc/{terminalId}/{handID}", method = RequestMethod.GET, produces = "application/json; charset=UTF-8")
	public JsonObject getDeviceMessage(@PathVariable("terminalId") Integer terminalId, @PathVariable("handID") Integer handID) throws Exception {
		JsonObject json = JsonObject.getInstance();
		HandleFaultDeviceItemDTO terminalMes = handleService.getDeivceMessage(terminalId, handID);
		json.setData(terminalMes);
		setJsonMesasge(json);
		return json;
	}
	
	
	@RequestMapping(value = "category", produces = "application/json; charset=utf-8")
	public JsonObject faultCategory() {
		JsonObject json = JsonObject.getInstance();
		json.setData(handleService.getFaultCategory());
		setJsonMesasge(json);
		return json;
	}
	
	private Predicate<Integer> typePred() {
		return  s -> { 
			if (FaultDeviceEnum.task_help_task.getId() == s
					|| FaultDeviceEnum.task_processed_task.getId() ==s
					|| FaultDeviceEnum.task_wait_handle.getId() ==s){
			    return true;
		    } 
	     return false;};
	}
	
	private Predicate<HandleFaultRecordDTO> validateRecord() {
	return s -> {
			
		if (    StringUtil.isEmpty(s.getPrinterPhoto()) || StringUtil.isEmpty(s.getTestPhoto())
				|| StringUtil.isEmpty(s.getDevicePhoto())|| StringUtil.isEmpty(s.getFaultCategoryIDs())
				|| ObjectUtil.isEmpty(s.getHandID()) || StringUtil.isEmpty(s.getMaintianRecord())
				|| !FaultDeviceConstant.constantMap.get("networkType").contains(s.getNetworkType())
				|| !FaultDeviceConstant.constantMap.get("signalLevel").contains(s.getSignalLevel())
				|| !FaultDeviceConstant.constantMap.get("recordStatus").contains(s.getRecordStatus())
				|| s.getNetworkType() == null || s.getSignalLevel()== null 
				) {
			return false;
		}
		return true;};	
	}
	
	public class UploadThread implements Callable<ResponseJson> {
		private String param ;
		
		public UploadThread(String param) {
			this.param = param;
		}
		
		@Override
		public ResponseJson call() throws Exception {
			String result = "";
			try {
				result = HttpClientUtil.post(HttpConfig.custom().url(upload_image_url).paramap(new HashMap(){{put("json_body", param);}}));
			} catch (Exception e) {
				e.printStackTrace();
			}
			log.info(result);
			return StringUtil.isEmpty(result)? new ResponseJson(): JSON.parseObject(result, ResponseJson.class);
		}
		
	} 
	
	
}
